package org.mixed.script.modules.http;

import org.mixed.script.annotation.Comment;
import org.mixed.script.annotation.Module;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

@Module("http")
public class HttpModule {

	private final RestTemplate template;
	private final HttpHeaders httpHeaders = new HttpHeaders();
	private final MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
	private UriComponentsBuilder builder;
	private Class<?> responseType = Object.class;
	private HttpMethod method = HttpMethod.GET;
    private Object requestBody;
	private MediaType contentType;

	public HttpModule(RestTemplate template) {
		this.template = template;
	}

	public HttpModule(RestTemplate template, String url) {
		this.template = template;
		this.builder = UriComponentsBuilder.fromHttpUrl(url);
	}

	@Comment("创建连接")
	public HttpModule connect(@Comment(name = "url", value = "目标URL") String url) {
		return new HttpModule(template, url);
	}

	@Comment("设置URI参数")
	public HttpModule param(@Comment(name = "name", value = "参数名") String name,
							@Comment(name = "values", value = "参数值") Object... values) {
		builder.queryParam(name, values);
		return this;
	}

	@Comment("批量设置URI参数")
	public HttpModule param(@Comment(name = "values", value = "参数值") MultiValueMap<String, String> params) {
		builder.queryParams(params);
		return this;
	}

	@Comment("设置header")
	public HttpModule header(@Comment(name = "key", value = "header名") String key,
							 @Comment(name = "value", value = "header值") String value) {
		httpHeaders.add(key, value);
		return this;
	}

	@Comment("批量设置header")
	public HttpModule header(@Comment(name = "values", value = "header值") MultiValueMap<String, String> values) {
		httpHeaders.addAll(values);
		return this;
	}

	@Comment("设置form参数")
	public HttpModule data(@Comment(name = "key", value = "参数名") String key,
						   @Comment(name = "values", value = "参数值") Object... values) {
		if (!ObjectUtils.isEmpty(values)) {
			for (Object value : values) {
				formData.add(key, value);
			}
		}
		return this;
	}

	@Comment("批量设置form参数")
	public HttpModule data(@Comment(name = "values", value = "参数值") MultiValueMap<String, Object> values) {
		formData.addAll(values);
		return this;
	}

	@Comment("设置`RequestBody`")
	public HttpModule body(@Comment(name = "requestBody", value = "`RequestBody`") Object requestBody) {
		this.requestBody = requestBody;
		return this;
	}

	@Comment("设置`ContentType`")
	public HttpModule contentType(@Comment(name = "contentType", value = "Content-Type值") String contentType) {
		return contentType(MediaType.parseMediaType(contentType));
	}

	@Comment("设置`ContentType`")
	public HttpModule contentType(@Comment(name = "mediaType", value = "Content-Type值") MediaType mediaType) {
		contentType = mediaType;
		return this;
	}

	@Comment("设置返回值为`byte[]`")
	public HttpModule expectBytes() {
		responseType = byte[].class;
		return this;
	}

	@Comment("发送`POST`请求")
	public ResponseEntity<?> post() {
		method = HttpMethod.POST;
		return execute();
	}

	@Comment("发送`GET`请求")
	public ResponseEntity<?> get() {
		method = HttpMethod.GET;
		return execute();
	}

	@Comment("发送`PUT`请求")
	public ResponseEntity<?> put() {
		method = HttpMethod.PUT;
		return execute();
	}

	@Comment("发送`DELETE`请求")
	public ResponseEntity<?> delete() {
		method = HttpMethod.DELETE;
		return execute();
	}

	@Comment("发送`HEAD`请求")
	public ResponseEntity<?> head() {
		method = HttpMethod.HEAD;
		return execute();
	}

	@Comment("发送`OPTIONS`请求")
	public ResponseEntity<?> options() {
		method = HttpMethod.OPTIONS;
		return execute();
	}

	@Comment("发送`TRACE`请求")
	public ResponseEntity<?> trace() {
		method = HttpMethod.TRACE;
		return execute();
	}

	@Comment("发送`PATCH`请求")
	public ResponseEntity<?> patch() {
		method = HttpMethod.PATCH;
		return execute();
	}

	@Comment("执行请求")
	public ResponseEntity<?> execute() {
        HttpEntity<Object> entity;
        if (formData.isEmpty()) {
			if (contentType == null) {
				// 如果没有明确设置contentType, 则用MediaType.APPLICATION_JSON
				contentType(MediaType.APPLICATION_JSON);
			}
			entity = new HttpEntity<>(requestBody, httpHeaders);
		} else {
			entity = new HttpEntity<>(formData, httpHeaders);
		}
		return template.exchange(builder.build().toUri(), method, entity, responseType);
	}
}
